"""
音频格式转换工具
支持将.m4a格式转换为.wav格式
"""

import os
import subprocess
import tempfile
from pathlib import Path
from typing import Optional, Tuple
import logging

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class AudioConverter:
    """音频格式转换器"""
    
    def __init__(self):
        """初始化转换器"""
        self.supported_input_formats = ['.m4a', '.mp3', '.aac', '.flac', '.ogg', '.wav']
        self.output_format = '.wav'
        
    def check_ffmpeg_available(self) -> bool:
        """检查FFmpeg是否可用"""
        try:
            result = subprocess.run(['ffmpeg', '-version'], 
                                  capture_output=True, text=True, timeout=10)
            return result.returncode == 0
        except (subprocess.TimeoutExpired, FileNotFoundError):
            return False
    
    def convert_to_wav(self, input_path: str, output_path: Optional[str] = None) -> Tuple[bool, str]:
        """
        将音频文件转换为WAV格式
        
        Args:
            input_path: 输入文件路径
            output_path: 输出文件路径（可选，默认在同目录生成）
            
        Returns:
            Tuple[bool, str]: (是否成功, 输出文件路径或错误信息)
        """
        try:
            input_file = Path(input_path)
            
            # 检查输入文件是否存在
            if not input_file.exists():
                return False, f"输入文件不存在: {input_path}"
            
            # 检查文件格式
            if input_file.suffix.lower() not in self.supported_input_formats:
                return False, f"不支持的文件格式: {input_file.suffix}"
            
            # 如果已经是WAV格式，直接返回原路径
            if input_file.suffix.lower() == '.wav':
                logger.info(f"文件已经是WAV格式: {input_path}")
                return True, input_path
            
            # 检查FFmpeg是否可用
            if not self.check_ffmpeg_available():
                return False, "FFmpeg未安装或不可用，请先安装FFmpeg"
            
            # 确定输出路径
            if output_path is None:
                output_path = str(input_file.with_suffix('.wav'))
            
            output_file = Path(output_path)
            
            # 创建输出目录（如果不存在）
            output_file.parent.mkdir(parents=True, exist_ok=True)
            
            # 构建FFmpeg命令
            cmd = [
                'ffmpeg',
                '-i', str(input_file),  # 输入文件
                '-acodec', 'pcm_s16le',  # 音频编码器
                '-ar', '16000',  # 采样率 16kHz
                '-ac', '1',  # 单声道
                '-y',  # 覆盖输出文件
                str(output_file)  # 输出文件
            ]
            
            logger.info(f"开始转换: {input_file.name} -> {output_file.name}")
            
            # 执行转换
            result = subprocess.run(cmd, capture_output=True, text=True, timeout=300)
            
            if result.returncode == 0:
                # 检查输出文件是否生成
                if output_file.exists() and output_file.stat().st_size > 0:
                    logger.info(f"转换成功: {output_file}")
                    return True, str(output_file)
                else:
                    return False, "转换失败：输出文件未生成或为空"
            else:
                error_msg = result.stderr or result.stdout or "未知错误"
                logger.error(f"FFmpeg转换失败: {error_msg}")
                return False, f"转换失败: {error_msg}"
                
        except subprocess.TimeoutExpired:
            return False, "转换超时（超过5分钟）"
        except Exception as e:
            logger.error(f"转换过程中发生错误: {str(e)}")
            return False, f"转换错误: {str(e)}"
    
    def convert_with_temp_file(self, input_path: str) -> Tuple[bool, str]:
        """
        转换音频文件并使用临时文件
        
        Args:
            input_path: 输入文件路径
            
        Returns:
            Tuple[bool, str]: (是否成功, 临时WAV文件路径或错误信息)
        """
        try:
            input_file = Path(input_path)
            
            # 如果已经是WAV格式，直接返回原路径
            if input_file.suffix.lower() == '.wav':
                return True, input_path
            
            # 创建临时文件
            with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as temp_file:
                temp_path = temp_file.name
            
            # 执行转换
            success, result = self.convert_to_wav(input_path, temp_path)
            
            if success:
                return True, temp_path
            else:
                # 清理临时文件
                try:
                    os.unlink(temp_path)
                except:
                    pass
                return False, result
                
        except Exception as e:
            return False, f"临时文件转换错误: {str(e)}"
    
    def get_audio_info(self, file_path: str) -> dict:
        """
        获取音频文件信息
        
        Args:
            file_path: 音频文件路径
            
        Returns:
            dict: 音频文件信息
        """
        try:
            if not self.check_ffmpeg_available():
                return {"error": "FFmpeg不可用"}
            
            cmd = [
                'ffprobe',
                '-v', 'quiet',
                '-print_format', 'json',
                '-show_format',
                '-show_streams',
                file_path
            ]
            
            result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
            
            if result.returncode == 0:
                import json
                info = json.loads(result.stdout)
                return info
            else:
                return {"error": f"获取音频信息失败: {result.stderr}"}
                
        except Exception as e:
            return {"error": f"获取音频信息错误: {str(e)}"}

    def convert_to_wav_compressed(self, input_path: str, output_path: Optional[str] = None, 
                                 target_size_mb: int = 30) -> Tuple[bool, str]:
        """
        将音频文件转换为压缩的WAV格式，控制文件大小
        
        Args:
            input_path: 输入文件路径
            output_path: 输出文件路径（可选）
            target_size_mb: 目标文件大小（MB）
            
        Returns:
            Tuple[bool, str]: (是否成功, 输出文件路径或错误信息)
        """
        try:
            input_file = Path(input_path)
            
            # 检查输入文件
            if not input_file.exists():
                return False, f"输入文件不存在: {input_path}"
            
            # 检查文件格式
            if input_file.suffix.lower() not in self.supported_input_formats:
                return False, f"不支持的文件格式: {input_file.suffix}"
            
            # 检查FFmpeg
            if not self.check_ffmpeg_available():
                return False, "FFmpeg未安装或不可用"
            
            # 确定输出路径
            if output_path is None:
                output_path = str(input_file.with_suffix('_compressed.wav'))
            
            output_file = Path(output_path)
            output_file.parent.mkdir(parents=True, exist_ok=True)
            
            # 获取音频信息
            audio_info = self.get_audio_info(str(input_file))
            if "error" in audio_info:
                return False, audio_info["error"]
            
            # 计算压缩参数
            duration = audio_info.get("duration", 0)
            if duration == 0:
                return False, "无法获取音频时长"
            
            # 计算目标比特率 (kbps)
            # 目标大小(MB) * 8(bits/byte) * 1024(KB/MB) / 时长(秒)
            target_bitrate = int((target_size_mb * 8 * 1024) / duration)
            target_bitrate = max(32, min(target_bitrate, 128))  # 限制在32-128kbps之间
            
            # 构建压缩转换命令
            cmd = [
                'ffmpeg',
                '-i', str(input_file),
                '-acodec', 'pcm_s16le',
                '-ar', '16000',  # 降低采样率到16kHz
                '-ac', '1',      # 单声道
                '-ab', f'{target_bitrate}k',  # 设置比特率
                '-y',
                str(output_file)
            ]
            
            logger.info(f"开始压缩转换: {input_file.name} -> {output_file.name} (目标: {target_size_mb}MB, 比特率: {target_bitrate}kbps)")
            
            # 执行转换
            result = subprocess.run(cmd, capture_output=True, text=True, timeout=600)
            
            if result.returncode == 0 and output_file.exists():
                # 检查压缩后的文件大小
                compressed_size_mb = output_file.stat().st_size / (1024 * 1024)
                logger.info(f"压缩完成: {compressed_size_mb:.1f}MB")
                return True, str(output_file)
            else:
                error_msg = result.stderr or "转换失败"
                logger.error(f"压缩转换失败: {error_msg}")
                return False, f"压缩转换失败: {error_msg}"
                
        except subprocess.TimeoutExpired:
            return False, "压缩转换超时（超过10分钟）"
        except Exception as e:
            logger.error(f"压缩转换过程中发生错误: {str(e)}")
            return False, f"压缩转换错误: {str(e)}"


def convert_audio_file(input_path: str, output_path: Optional[str] = None) -> Tuple[bool, str]:
    """
    便捷函数：转换音频文件为WAV格式
    
    Args:
        input_path: 输入文件路径
        output_path: 输出文件路径（可选）
        
    Returns:
        Tuple[bool, str]: (是否成功, 输出文件路径或错误信息)
    """
    converter = AudioConverter()
    return converter.convert_to_wav(input_path, output_path)


if __name__ == "__main__":
    # 测试代码
    converter = AudioConverter()
    
    # 检查FFmpeg
    if converter.check_ffmpeg_available():
        print("✓ FFmpeg可用")
    else:
        print("✗ FFmpeg不可用，请先安装FFmpeg")
        exit(1)
    
    # 测试转换（如果有测试文件）
    test_file = "recordings/4.24公司晨会.m4a"
    if os.path.exists(test_file):
        print(f"\n测试转换文件: {test_file}")
        success, result = converter.convert_to_wav(test_file)
        if success:
            print(f"✓ 转换成功: {result}")
        else:
            print(f"✗ 转换失败: {result}")
    else:
        print(f"\n测试文件不存在: {test_file}")